package it.bambo.tankwars;

import it.bambo.tankwars.model.*;
import wiiusej.WiiUseApiManager;
import wiiusej.Wiimote;
import wiiusej.wiiusejevents.physicalevents.*;
import wiiusej.wiiusejevents.utils.WiimoteListener;
import wiiusej.wiiusejevents.wiiuseapievents.*;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;

/**
 * Andreas Baumgartner: andreas@bambo.it
 */
public class Tankwars extends JFrame implements WiimoteListener {

    private BattleField battleField;

    public Tankwars(String title) {
        super(title);
    }

    public static void main(String[] args) {
        Tankwars main = new Tankwars("Tank Wars");
        main.run();
    }

    public void run() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(800, 600);
        setVisible(true);

        battleField = new BattleField(new Rectangle(800, 600));
        getContentPane().add(battleField);

        new Tank(battleField, Color.BLUE, ControlType.KEYBOARD, new Point(10, 10));
        new Tank(battleField, Color.GREEN, ControlType.WIIMOTE2, new Point(10, 60));

        new Tank(battleField, Color.RED, ControlType.BOT, new Point(400, 10));
        new Tank(battleField, Color.RED, ControlType.BOT, new Point(300, 60));
        new Tank(battleField, Color.RED, ControlType.BOT, new Point(200, 130));
        new Tank(battleField, Color.RED, ControlType.BOT, new Point(100, 190));

        Thread repaintThread = new Thread() {
            @Override
            public void run() {
                while (true) {
                    for (Unit unit : battleField.getUnits()) {
                        if (unit instanceof Bullet) {
                            Bullet bullet = (Bullet) unit;
                            bullet.fly();
                        }
                    }
                    battleField.repaint();
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        repaintThread.start();

        addKeyListener(new KeyAdapter() {

            private Set<Integer> pressedKeys = new HashSet<Integer>();

            @Override
            public void keyPressed(KeyEvent e) {
                pressedKeys.add(e.getKeyCode());
                for (Unit unit : battleField.getUnits()) {
                    if (ControlType.KEYBOARD.equals(unit.getControlType())) {
                        if (pressedKeys.contains(KeyEvent.VK_UP) && pressedKeys.contains(KeyEvent.VK_RIGHT)) {
                            unit.executeCommand(new Command(CommandType.DIRECTION, 45));
                        } else if (pressedKeys.contains(KeyEvent.VK_DOWN) && pressedKeys.contains(KeyEvent.VK_RIGHT)) {
                            unit.executeCommand(new Command(CommandType.DIRECTION, 135));
                        } else if (pressedKeys.contains(KeyEvent.VK_DOWN) && pressedKeys.contains(KeyEvent.VK_LEFT)) {
                            unit.executeCommand(new Command(CommandType.DIRECTION, 225));
                        } else if (pressedKeys.contains(KeyEvent.VK_UP) && pressedKeys.contains(KeyEvent.VK_LEFT)) {
                            unit.executeCommand(new Command(CommandType.DIRECTION, 315));
                        } else if (pressedKeys.contains(KeyEvent.VK_UP)) {
                            unit.executeCommand(new Command(CommandType.DIRECTION, 0));
                        } else if (pressedKeys.contains(KeyEvent.VK_RIGHT)) {
                            unit.executeCommand(new Command(CommandType.DIRECTION, 90));
                        } else if (pressedKeys.contains(KeyEvent.VK_DOWN)) {
                            unit.executeCommand(new Command(CommandType.DIRECTION, 180));
                        } else if (pressedKeys.contains(KeyEvent.VK_LEFT)) {
                            unit.executeCommand(new Command(CommandType.DIRECTION, 270));
                        }

                        if (pressedKeys.contains(KeyEvent.VK_SPACE)) {
                            unit.executeCommand(new Command(CommandType.FIRE));
                        }

                        if (pressedKeys.contains(KeyEvent.VK_A)) {
                            unit.executeCommand(new Command(CommandType.TOWER_CHANGE, -10));
                        } else if (pressedKeys.contains(KeyEvent.VK_D)) {
                            unit.executeCommand(new Command(CommandType.TOWER_CHANGE, 10));
                        }
                    }
                }
            }

            @Override
            public void keyReleased(KeyEvent e) {
                pressedKeys.remove(e.getKeyCode());
            }
        });

        Wiimote[] wiimotes = WiiUseApiManager.getWiimotes(2, true);
        for (Wiimote wiimote : wiimotes) {
            wiimote.addWiiMoteEventListeners(this);
            System.out.println("Wiimote connected: " + wiimote.getId());
        }
    }

    @Override
    public void onButtonsEvent(WiimoteButtonsEvent wiimoteButtonsEvent) {
        ControlType controllerType = ControlType.getControllerType(wiimoteButtonsEvent.getWiimoteId());
        for (Unit unit : battleField.getUnits()) {
            if (controllerType.equals(unit.getControlType())) {
                if (wiimoteButtonsEvent.isButtonAJustPressed()) {
                    unit.executeCommand(new Command(CommandType.FIRE));
                }
                if (wiimoteButtonsEvent.isButtonUpHeld() && wiimoteButtonsEvent.isButtonRightHeld()) {
                    unit.executeCommand(new Command(CommandType.DIRECTION, 45));
                } else if (wiimoteButtonsEvent.isButtonDownHeld() && wiimoteButtonsEvent.isButtonRightHeld()) {
                    unit.executeCommand(new Command(CommandType.DIRECTION, 135));
                } else if (wiimoteButtonsEvent.isButtonDownHeld() && wiimoteButtonsEvent.isButtonLeftHeld()) {
                    unit.executeCommand(new Command(CommandType.DIRECTION, 225));
                } else if (wiimoteButtonsEvent.isButtonUpHeld() && wiimoteButtonsEvent.isButtonLeftHeld()) {
                    unit.executeCommand(new Command(CommandType.DIRECTION, 315));
                } else if (wiimoteButtonsEvent.isButtonUpHeld()) {
                    unit.executeCommand(new Command(CommandType.DIRECTION, 0));
                } else if (wiimoteButtonsEvent.isButtonRightHeld()) {
                    unit.executeCommand(new Command(CommandType.DIRECTION, 90));
                } else if (wiimoteButtonsEvent.isButtonDownHeld()) {
                    unit.executeCommand(new Command(CommandType.DIRECTION, 180));
                } else if (wiimoteButtonsEvent.isButtonLeftHeld()) {
                    unit.executeCommand(new Command(CommandType.DIRECTION, 270));
                }
            }
        }
    }

    @Override
    public void onIrEvent(IREvent irEvent) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void onMotionSensingEvent(MotionSensingEvent motionSensingEvent) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void onExpansionEvent(ExpansionEvent expansionEvent) {
        ControlType controllerType = ControlType.getControllerType(expansionEvent.getWiimoteId());
        for (Unit unit : battleField.getUnits()) {
            if (controllerType.equals(unit.getControlType())) {
                if (expansionEvent instanceof NunchukEvent) {
                    NunchukEvent nunchukEvent = (NunchukEvent) expansionEvent;
                    float angle = nunchukEvent.getNunchukJoystickEvent().getAngle();
                    if (!(angle == Float.NaN)) {
                        unit.executeCommand(new Command(CommandType.TOWER_ABSOLUT, angle - 90));
                    }
                }
            }
        }
    }


    @Override
    public void onStatusEvent(StatusEvent statusEvent) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void onDisconnectionEvent(DisconnectionEvent disconnectionEvent) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void onNunchukInsertedEvent(NunchukInsertedEvent nunchukInsertedEvent) {
        System.out.println("Nunchuck connected: " + nunchukInsertedEvent.getWiimoteId());
    }

    @Override
    public void onNunchukRemovedEvent(NunchukRemovedEvent nunchukRemovedEvent) {
        System.out.println("Nunchuck removed: " + nunchukRemovedEvent.getWiimoteId());
    }

    @Override
    public void onGuitarHeroInsertedEvent(GuitarHeroInsertedEvent guitarHeroInsertedEvent) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void onGuitarHeroRemovedEvent(GuitarHeroRemovedEvent guitarHeroRemovedEvent) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void onClassicControllerInsertedEvent(ClassicControllerInsertedEvent classicControllerInsertedEvent) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void onClassicControllerRemovedEvent(ClassicControllerRemovedEvent classicControllerRemovedEvent) {
        //To change body of implemented methods use File | Settings | File Templates.
    }
}
